package utils.node;

/**
 * @Author:      Tara.Li(李春侣)
 * @Contact Me WeChat: flyme9988
 * @ReWroteBy:
 * @Date:  2021-12-19 20:23:08
 * @Description:  设计一个栈，无论怎么压栈，弹出，都能以最小的时间复杂度，获取栈中的最小元素。
 */
public class StackMin {
    //定义一个正常存储的栈
    private Stack<Integer> stackData;
    // 定义一个存储最小元素的栈，
    private Stack<Integer> stackMin;

    //构造函数

    public StackMin() {
        stackData = new Stack<>();
        stackMin = new Stack<>();
    }
    /**
     * 压栈
     * @param newNum 新压入栈的值
     */
    public void push(int newNum){
        //如果记录最小值的栈为空，，即为第一个元素，直接两个栈都进。
        if (this.stackMin.isEmpty()){
            stackMin.push(newNum);

            // 如果新压入的元素小于stackMin元素的栈顶元素，就压入栈顶。
        }else if (newNum < this.stackMin.peek()) {
            stackMin.push(newNum);

            // 如果新压入的元素大于等于stackMin元素，就再压一次栈顶元素。
        }else if (newNum >= this.stackMin.peek()){
            Integer temp = this.stackMin.peek();
            this.stackMin.push(temp);
        }

        // 无论stackMin怎么变动，stackData都是正常push值的
        stackData.push(newNum);
    }

    /**
     * 弹出按照正常情况弹出stackData栈的数据
     * @return
     */
    public Object pop(){
        //判断栈是不是为空
        if (stackData.isEmpty()){
            throw new RuntimeException("当前栈元素已经空了");
        }
        // 两个同步弹出，保证栈内元素一致。
        stackMin.pop();
        return  stackData.pop();
    }

    /**
     * 获取最小元素
     * @return
     */
    public Object getMin(){
        //判断栈是不是为空
        if (stackData.isEmpty()){
            throw new RuntimeException("当前栈元素已经空了");
        }
        //当前栈顶永远存储的是最小元素。
        return this.stackMin.peek();
    }
}
